package cbbx_sm.utils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import cbbx_sm.decision_maker.search.States.NNProperty;
import cbbx_sm.evaluation.CompareAlternativeSchedulers;

/**
 * @author ronenvaisenberg
 * 
 * A utility class for controlling the different parameters of an experiment.
 * The class reads the standard program arguments (String[] args) and attempts to find
 * a field named with the same name as the parameter, if it does find it, it will set the field based on the 
 * given value.
 * 
 * Example usage: java -jar ExperimentManager.jar runBaselineAlternatives=true performOracle=true 
 */
public class ExperimentManager {
	public static int boxLocationId = 1; // face.
	public static boolean isJarred = false;
	public static String fileNameFormat = "data/cameraData/%s%s.txt";
	public static String eventsToCatchFile = "data/eventsToCatch.txt";
	public static String statesInitialFolder = "data/statesData/";
	public static String testDay = "20090528";
	public static String trainDay = "20090527";
	
	// Used to study the scheduler's behaviour.
	public static boolean fixCameraData = true;

	public static boolean runBaselineAlternatives = false;
	public static boolean runMostLikelyAlternative = false;
	public static boolean performTreeLookahead = true;
	public static int numberOfTimeStampsLookAheadTree = 2;
	public static boolean treeLookaheadRecordsMisses = true;

	public static boolean performLookahead1 = false;
	public static boolean performOracle = false;
	public static boolean performSmartMostLikely = false;

	
	public static int numberOfTimeStampsLookAhead = 15;
	public static boolean runLookAheadAlternatives = false;
	public static boolean performExtraExperiments = false;

	// Approximation techniques.
	public static NNProperty approximationTechnique = NNProperty.nn;
	public static NNProperty scoreUsed = NNProperty.nn;
	
	// Lookup the action in the table directly.
	// Correlated with timeInFuture.
	public static boolean directActionLookup = true;
	// Number of seconds in the future that the probabilistic model is used.
	public static int timeInFuture = 0;
	
	public static boolean increaseBeta = false;
	
	// Are we using the apriori probabilities to compute the probability of motion.
	public static boolean useAprioriProb = true;
	
	// Are we using the apriori probabilities to roll the probabilities forward.
	public static boolean useAprioriWhenRollingForward = true;
	
	// Are we using the probabilities of motion when moving forward.
	public static boolean useNonSeenMotion = true;

	// Are we using the transition probabilities from no motion as well.
	public static boolean useFromZeroTransitionProb = false;
	
	// Should always be true, this takes care of the bug of trying to predict the motion
	// of something that we have just seen that there is no motion.
	public static boolean useSeenAsPrediction = true;
	
	public static boolean largeNetwork = false;
	public static boolean useManualDataFormat = false;

	public static boolean noCache = true;
	public static String lookaheadPolicyFolder = "output/policies/";

	public static boolean discounting = false;
	public static double utilityZoom = 1;
	public static double utilityUP = 0;
	public static double utilityUPStartValue = 0;
	public static double utilityUPEndValue = 1;
	

	public static double error = 0.01;
	public static int numberOfSecondsCorrelation = 15;
	public static boolean usePreComputedGrid = false;

	public static int topK = 5000;
	
	// How fine grained is the initial grid.
	// E.g., 10 means 0,0.1,0.2,...,0.9,1
	public static int numberOfEventPossibleValues = 2;
	public static int numberOfClustersStart = 5;
	public static int numberOfClustersEnd = 5;



	public static int stateSize = 15000;
	public static int maxStateSize = 40000;
	public static int sizeToGenerateAll = 40000;
	
	public static boolean isViewEnabled = false;
	public static boolean debug = false;

	public static String IMAGE_STREAM_DIRECTORY = "/Volumes/Iomega_Ext Drive/20090528";
		//null;
	public static String outputFilename = "output/schedulerEvaluationResults.txt";
	
	private static Map<String, Field> constantsMap =
		new HashMap<String, Field>();
	static {
		for (Field f : ExperimentManager.class.getDeclaredFields()) {
			constantsMap.put(f.getName(), f);
		}
	}
	
	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		for (String arg : args) {
			setFlag(arg.split("=")[0], arg.split("=")[1]);
		}
		for (Field f : ExperimentManager.class.getDeclaredFields()) {
			System.out.println(f.getName() + "=" + f.get(new String()));
		}
		CompareAlternativeSchedulers tester = new CompareAlternativeSchedulers();
		validateParameters();
		tester.compareAlternatives();
	}
	
	private static void validateParameters() {
		assert((timeInFuture == 0 && directActionLookup) 
				||
				(timeInFuture == 1 && !directActionLookup));		
	}

	public static void setFlag(String flagName, String value) throws IllegalArgumentException, IllegalAccessException {
		Field f = constantsMap.get(flagName);
		System.out.println(f.getName());
		if (f.getType() == boolean.class) {
			f.set(null, Boolean.parseBoolean(value));
		}
		if (f.getType() == int.class) {
			f.set(null, Integer.parseInt(value));			
		}
		if (f.getType() == double.class) {
			f.set(null, Double.parseDouble(value));	
		}
		if (f.getType() == String.class) {
			f.set(null, value);
		}
	}
}
